package ru.kisa_wst.parse;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Parser {

	public static void main(String[] arg) {
		Parser parser = new Parser();
		//Collection<String> links = parser.getLinks("http://birja.ru/?id=7");
		Collection<String> links = parser.getLinks("http://yandex.ru/");
		for (String link : links) {
			System.out.println(link);
		}
	}
	
	/**
	 * @param page - Source of page
	 * @return - Collection of links that was found
	 */
	public Collection<String> getLinks(String url) {
		Collection<String> result = new ArrayList<String>();
		StringBuffer page = null;
		Parser parser = new Parser();
		try {
			page = parser.readPage(url);
		} catch (IOException e) {
			System.out.println("Error while reading the page:");
			System.out.println(e);
		}
		if (page != null && page.length() > 1) {
			//not formated links
			Collection<String> foundLinks = parser.getUnformattedLinks(page);
			for (String foundLink : foundLinks) {
				Link link = new Link(url, foundLink);
				String tmp = link.getLink();
				if (tmp != null && tmp.length() > 0) {
					result.add(tmp);
				}
			}
		}
		Link urlLink = new Link(url);
		result = filterLinks(result, urlLink.getDomain());		
		return result;
	}
	
	/*
	public Collection<String> getLinks(String url) {
		Collection<String> result = new ArrayList<String>();
		StringBuffer page = null;
		Parser parser = new Parser();
		try {
			page = parser.readPage(url);
		} catch (IOException e) {
			System.out.println("Error while reading the page:");
			System.out.println(e);
		}
		if (page != null && page.length() > 1) {
			//not formated links
			Collection<String> links1 = parser.getUnformattedLinks(page);
			//formated links
			Collection<String> links2 = new ArrayList<String>();
			for (String link : links1) {
				String tmpLink = parser.formatLink(url, link);
				links2.add(tmpLink);
			}
			//filtered links
			Collection<String> links3 = parser.filterLinks(links2);
			//formated links
			Collection<String> links4 = new ArrayList<String>();
			for (String link : links3) {
				String tmpLink = parser.formatLink(url, link);
				links4.add(tmpLink);
			}
			System.out.println("Found links:");
			for (String link: links4) {
				System.out.println(link);
				result.add(link);
			}
		}
		return result;
	}
	*/
		
	/**
	 * 
	 * @param url - URL of reading page
	 * @return - Source of page
	 * @throws IOException
	 */
	private StringBuffer readPage(String url) throws IOException {
		URLConnection url_con = new URL(url).openConnection();

		InputStreamReader reader = new InputStreamReader(url_con.getInputStream());
		StringBuffer buffer_s = new StringBuffer();

		int length=0;

		while (true) {
			int i = reader.read();
			if (i==-1) break;
			char x = (char)i;
			buffer_s.append(x);
			length++;
		}
		reader.close();

		return buffer_s;
	}
	
	/**
	 * 
	 * @param page - Source of page
	 * @return - Collection of links that was found
	 */
	private Collection<String> getUnformattedLinks(StringBuffer page) {
		Collection<String> links = new ArrayList<String>();
		
		//Find <a> tags
		Pattern pattern = Pattern.compile("<a[^>]*");
		Matcher matcher = pattern.matcher(page);

		while (matcher.find()) {
			String r1 = matcher.group();
			
			//Find 'href' parameter of link
			Pattern pattern1 = Pattern.compile("href[\\s]*=[\\s]*[\"]?[^\\s\"]*");
			Matcher matcher1 = pattern1.matcher(r1);
			String r2;
			if (matcher1.find()) {
				r2 = matcher1.group();
				//Get only links
				Pattern pattern2 = Pattern.compile("(href[\\s]*=[\\s]*[\"]?)");
				Matcher matcher2 = pattern2.matcher(r2);
				String r3;
				if (matcher2.find()) {
					r3 = matcher2.replaceAll("");
					links.add(r3);
				}
			}
			
			
		}
		return links;
	}	

	/**
	 * 
	 * @param domen - URL of domen in 'http://xxx.xxx' format
	 * @param link - Link that shold be connected to domen
	 * @return - URL in format 'http://xxx.xxx/link'
	 */
	private String formatLink(String domain, String link) {
		
		/* FIXME
		 * This method should be replaced to especial util class,
		 * for example LinkUtil.java
		 */
		
		String result = link;
		
		if (domain.lastIndexOf("/") == domain.length()-1) {
			domain = domain.substring(0, domain.length()-1);
		}
		
		if (link.indexOf("/") == 0 ) {
			result = domain + link;
		} else if (link.length() > 6 && "http://".equalsIgnoreCase(link.substring(0, 7))) {
			result = link;
		} else if (link.length() > 7 && "https://".equalsIgnoreCase(link.substring(0, 8))) {
			result = link;
		}
		else {
			link = "/" + link;
			result = domain + link; 
		}
		if (result.lastIndexOf("/") == result.length() - 1) {
			result = result.substring(0, result.length() - 1);
		}
			
		return result;
	}
	
	private Collection<String> filterLinks(Collection<String> input, String domain) {
		Set<String> buffer = new HashSet<String>();
		for (String tmp : input) {
			Link tmpLink = new Link(tmp);
			if (domain.equals(tmpLink.getDomain())) {
				buffer.add(tmp);
				
				if (tmp.indexOf("?") > 1) {
					String linkWithoutRequest = tmp.substring(0, tmp.indexOf("?"));
					buffer.add(linkWithoutRequest);
				}
			}
		}
		Collection<String> output = new ArrayList<String>(buffer);
		return output;
	}
	
	public static void main2(String[] arg) {
		Parser parser = new Parser();
		System.out.println(parser.getDomain("http://google.com"));
		System.out.println(parser.getDomain("http://google.com/search"));
		System.out.println(parser.getDomain("https://google.com?qwerty"));
		System.out.println(parser.getDomain("http://google.com/search/search?qwerty"));
		System.out.println(parser.getDomain("ftp://google.com?qwerty/search"));
		System.out.println(parser.getDomain("http://google.com.org/"));
	}
	
	/**
	 * 
	 * @param link - Any link in 'http://<domain>/xxx/xxx' format
	 * @return - Reference to domain in 'http://<domain>' format 
	 */
	private String getDomain(String link) {
		String result = link;
		Pattern pattern = Pattern.compile(".{1,5}://[^/?]*");
		Matcher matcher = pattern.matcher(link);
		if (matcher.find()) {
			result = matcher.group();
		}
		return result;
	}
}
